package com.daxue.localserver.test;

import java.util.Arrays;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.IntStream;

/**
 * @author daxue0929
 * @date 2022/10/10
 */

public class BoundedContainer {

    private final String[] elements = new String[10];
    //可重入锁
    private final Lock lock = new ReentrantLock();
    /**
     * 非空的条件队列
     */
    private final Condition notEmptyCondition = lock.newCondition();

    private int elementCount; // 数组中已有的元素个数
    private int putIndex = 0; // 放置元素索引, 默认是 0
    private int takeIndex = 0; //提取元素索引, 默认是 0


//    @Test
    public void main(){
        BoundedContainer boundedContainer = new BoundedContainer();
        IntStream.range(0,10).forEach(i-> new Thread(() -> {
            try {
                boundedContainer.put("hello");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "thread-put-" + i).start());

        IntStream.range(0,10).forEach(i-> new Thread(() -> {
            try {
                boundedContainer.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "thread-take-" + i).start());


    }

    /**
     * 获取元素的方法
     */
    public void take() throws InterruptedException {
        this.lock.lock();
        try {
            while (this.elementCount == 0) {
                notEmptyCondition.await();
            }
            elements[takeIndex] = null;
            if (takeIndex++ == this.elements.length){
                takeIndex = 0;
            }
            elementCount--;
            System.out.println(Thread.currentThread().getName() + " put method " + Arrays.asList(elements));
            notEmptyCondition.signal(); // 唤醒一个等待的线程
        }finally {
            this.lock.unlock();
        }
    }


    /**
     * 放置元素的方法
     * @param element 需要放置的目标元素
     * @throws InterruptedException
     */
    public void put(String element) throws InterruptedException {
        this.lock.lock(); //当前线程持有锁
        try {
            //如果数组已经放满，就先等待
            while (this.elementCount == this.elements.length) {
                notEmptyCondition.await();
            }
            elements[putIndex] = element;
            if (putIndex++ == this.elements.length) {
                putIndex = 0;
            }
            elementCount++;
            System.out.println(Thread.currentThread().getName() + " put method " + Arrays.asList(elements));
            notEmptyCondition.signal(); // 唤醒一个等待的线程
        }finally {
            this.lock.unlock();
        }
    }






}
